#include <QDir>
#include <QPluginLoader>
#include <qDebug>
#include <QMenu>
#include <QAction>
#include <QFile>
#include <QTextStream>
#include <QSettings>
#include <QTextCodec>
#include <QScreen>
#include <QPainter>
#include <qmath.h>

#include <QTableWidget>
#include <QTableWidgetItem>
#include <QHeaderView>
#include <QToolTip>
#include <QHBoxLayout>

#include "qlscoresystem.h"
#include "ui_qlscoresystem.h"
#include "../DevBase/dllQLsLog/dllqlslog.h"
#include "../DevBase/dllQLsLanguagesManager/qlslanguagesmanager.h"
#include "../../inc/QLsFunc/qlsfunc.h"

static const QString g_pluginsDir = "plugins/QCoreSystem";

static const int MIN_WIDTH = 628;
static const int MIN_HEIGHT = 304;
static const int STACKEDWIDGET_MIN_WIDTH = 618;
static const int STACKEDWIDGET_MIN_HEIGHT = 174;

static const int SHADOW_WIDTH = 10;		/* 阴影边框宽度 */

QLsCoreSystem::QLsCoreSystem(QWidget *parent)
	: QWidget(parent)
	, ui(new Ui::QLsCoreSystem)
	, m_miniWidth(MIN_WIDTH)
	, m_miniHeight(MIN_HEIGHT)
	, m_tabWidgetMiniWidth(STACKEDWIDGET_MIN_WIDTH)
	, m_tabWidgetMiniHeight(STACKEDWIDGET_MIN_HEIGHT)
	#if IsBorderLess
	, m_bSize(true)
	, m_bMove(true)
	, m_bSizeOrMove(true)
	, m_bPress(false)
	#endif
{
	ui->setupUi(this);

	/* 日志初始化 */
	DllQLsLog::GetInstance().SetLogWindow(this);

	/* 主界面初始化 */
	HomeInit();

	/* 设置初始化 */
	SetInit();
}

QLsCoreSystem::~QLsCoreSystem()
{
	delete ui;
}
#if IsBorderLess
/* 鼠标事件重载 - 移动事件 */
void QLsCoreSystem::mouseMoveEvent(QMouseEvent *event)
{
	if(m_bPress)
	{
		if(isMaximized()) return;
		/* 缩放 */
		if(m_bSizeOrMove)
		{
			if(m_bSize)
			{
				QPoint pt = event->pos();
				resize(qMax(pt.x(), m_miniWidth), qMax(pt.y(),m_miniHeight));
			}
		}
		/* 移动 */
		else
		{
			if(m_bMove)
				move(event->globalPos() - m_PointWindow);
		}
	}

	QWidget::mouseMoveEvent(event);
}

/* 鼠标事件重载 - 按下事件 */
void QLsCoreSystem::mousePressEvent(QMouseEvent *event)
{
	if(event->buttons() == Qt::LeftButton)
	{	/* 缩放：在右下20px处 */
		if(width() - 20 < event->pos().x() && event->pos().x() < width() &&
				height() - 20 < event->pos().y() && event->pos().y() < height())
		{
			m_bSizeOrMove = true;
		}
		/* 移动 */
		else
		{
			m_bSizeOrMove = false;
			m_PointWindow = event->globalPos() - pos();
		}
		m_bPress = true;
		QWidget::mousePressEvent(event);
	}
}

/* 鼠标事件重载 - 释放事件 */
void QLsCoreSystem::mouseReleaseEvent(QMouseEvent *event)
{
	m_bPress = false;
	QWidget::mouseReleaseEvent(event);
}
#endif
/* 事件过滤器 */
bool QLsCoreSystem::eventFilter(QObject *target, QEvent *event)
{
	/* 标题栏双击 最大化/还原窗口 */
	if(target == ui->topWidget)
	{
		if(event->type() == QEvent::MouseButtonDblClick)
		{
			on_maxiBtn_clicked();
			return true;
		}
	}

	return QWidget::eventFilter(target, event);
}

/* 绘图事件重载 */
void QLsCoreSystem::paintEvent(QPaintEvent *event)
{
#if IsShadow
	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing, true);
	painter.fillRect(
				QRect(
					SHADOW_WIDTH, SHADOW_WIDTH,
					width() - 2 * SHADOW_WIDTH,
					height() - 2 * SHADOW_WIDTH),
				QBrush(Qt::white));

	QColor color(0, 0, 0, 30);
	for (int i = 0; i < SHADOW_WIDTH; i++)
	{
		color.setAlpha(qvariant_cast<int>(200 - (double)i / SHADOW_WIDTH * 200));
		painter.setPen(color);
		// 圆角阴影边框;
		painter.drawRoundedRect(
					SHADOW_WIDTH - i, SHADOW_WIDTH - i,
					width() - (SHADOW_WIDTH - i) * 2,
					height() - (SHADOW_WIDTH - i) * 2, 4, 4);
	}
#endif

	QWidget::paintEvent(event);
}

/* 主界面初始化 */
void QLsCoreSystem::HomeInit()
{
#if AUTO_ScaleUI
	m_miniWidth = ScaleUI(m_miniWidth);
	m_miniHeight = ScaleUI(m_miniHeight);
	m_tabWidgetMiniWidth = ScaleUI(m_tabWidgetMiniWidth);
	m_tabWidgetMiniHeight = ScaleUI(m_tabWidgetMiniHeight);
#endif

	/* 整个窗口大小初始化，重设大小，解决 qss样式更改 及 代码初始化 导致的窗口大小嵌入冲突 */
	if(width() < m_miniWidth || height() < m_miniHeight)
		resize(m_miniWidth, m_miniHeight);
#if IsBorderLess
	/* 隐藏窗口，只显示控件 */
	setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
	setAttribute(Qt::WA_TranslucentBackground);
#endif
	/* 标题栏注册事件过滤器，处理双击事件 */
	ui->topWidget->installEventFilter(this);
	ui->showTabWidget->installEventFilter(this);

	/* 日志显示表格初始化 */
	ui->recordTableWidget->horizontalHeader()->setDefaultAlignment(
				Qt::AlignHCenter | Qt::AlignVCenter);
	/* 样式 */
	ui->recordTableWidget->horizontalHeader()->setSectionResizeMode(
				0, QHeaderView::ResizeToContents);		/* 自动适应内容 */
	ui->recordTableWidget->horizontalHeader()->setSectionResizeMode(
				1, QHeaderView::ResizeToContents);		/* 自动适应内容 */
	ui->recordTableWidget->horizontalHeader()->setSectionResizeMode(
				2, QHeaderView::Stretch);				/* 自动列宽并等宽 */

	/* 插件管理 */
//	ui->showTabWidget->setTabStyle(QLsPluginsManagerAppfwk::QLsTabStyle::WEST);
	ui->showTabWidget->setPluginsDir(g_pluginsDir);
	connect(this, &QLsCoreSystem::sigLoad, ui->showTabWidget, &QLsPluginsManagerAppfwk::slotPluginLoad);
	connect(ui->showTabWidget, &QLsPluginsManagerAppfwk::sigChangeMinimumSize,
			this, &QLsCoreSystem::slotShowTabWidgetChangeMinimumSize);

	/* 软件名 */
	QSettings settings("ini/info.ini", QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
	ui->titleLabel->setText(settings.value("sys/name", tr("插件管理系统")).toString());
}

/* 设置初始化 */
void QLsCoreSystem::SetInit()
{
	/* ----- 设置的开头 ----- */
	/* 初始化本地主题 */
	QSettings settings(QString("ini/themes/%1.ini").arg(g_pluginsDir), QSettings::IniFormat);
	settings.setIniCodec(QTextCodec::codecForName("UTF-8"));
	m_curThemeName = settings.value("cur/theme", "white").toString();
	ui->showTabWidget->setCurThemeName(m_curThemeName);
	QLsThemesManager *themesManager = ui->showTabWidget->themesManager();
	themesManager->LoadTheme(this, m_curThemeName);

	/* 当前语言初始化 */
	QLsLanguagesManager &languagesManager = QLsLanguagesManager::GetInstance();
	m_curLangPack = languagesManager.GetCurrentLangPack();

	/* 添加设置按钮菜单 */
	QMenu *setMenu = new QMenu;
	ui->setBtn->setMenu(setMenu);

	/* ----- 设置的中间 ----- */
	/* 设置主题 */
	QMenu *setThemesMenu = setMenu->addMenu(tr("设置主题"));
	/* 获取当前可用主题 */
	foreach (QString theme, themesManager->GetThemes())
	{
		/* 创建动作组 */
		QAction *action = new QAction(theme, this);

		/* 加入二级菜单 */
		setThemesMenu->addAction(action);

		action->setCheckable(true);
		if(theme == m_curThemeName)
			action->setChecked(true);
		else action->setChecked(false);
		connect(action, &QAction::triggered, this, &QLsCoreSystem::slotSetThemesActionsTriggered);
	}

	/* 加载全部插件 */
	ui->showTabWidget->LoadAllPlugin();

	/* 切换语言 */
	QMenu *changeLanguageMenu = setMenu->addMenu(tr("切换语言"));
	foreach (QString langPack, languagesManager.GetLangPacks())
	{
		/* 创建动作组 */
		QAction *action = new QAction(langPack, this);

		/* 加入二级菜单 */
		changeLanguageMenu->addAction(action);

		action->setCheckable(true);
		if(langPack == m_curLangPack)
			action->setChecked(true);
		else action->setChecked(false);
		connect(action, &QAction::triggered, this, &QLsCoreSystem::slotChangeLanguageActionsTriggered);
	}
}
#if AUTO_ScaleUI
/* 缩放UI */
int QLsCoreSystem::ScaleUI(int spec)
{
	double rate = 0;		/* 比例 */

	QList<QScreen*> screens = QApplication::screens();
	if(screens.size() > 0)
	{
		QScreen* screen = screens[0];
		double dpi = screen->logicalDotsPerInch();
		rate = dpi / 96.0;

		if (rate < 1.1) rate = 1.0;
		else if (rate < 1.4) rate = 1.25;
		else if (rate < 1.6) rate = 1.5;
		else if (rate < 1.8) rate = 1.75;
		else rate = 2.0;
	}

	m_preRate = rate;
	return (int)(spec * rate);
}

/* 根据缩放设置尺寸 */
void QLsCoreSystem::SetSizeWithScale(const QObject &obj)
{
	for(int i = 0; i < obj.children().size(); i++)
	{
		QWidget *pWidget = qobject_cast<QWidget *>(obj.children().at(i));
		if(pWidget != nullptr)
		{
			QSize preSize = pWidget->size();
			pWidget->setMinimumSize(pWidget->minimumSize()*m_scaleFromPreRate);
			pWidget->setMaximumSize(
						qMin((int)(pWidget->maximumWidth()*m_scaleFromPreRate), 16777215),
						qMin((int)(pWidget->maximumHeight()*m_scaleFromPreRate), 16777215));
			pWidget->resize(preSize*m_scaleFromPreRate);
			SetSizeWithScale(*(obj.children().at(i)));
		}
	}
}
#endif
/* 最大化/还原窗口 */
void QLsCoreSystem::on_maxiBtn_clicked()
{
	/* 还原 */
	if(isMaximized())
	{
		/* 显示阴影边框 */
		ui->coreSystemGLayout->setMargin(5);

		/* 还原 */
		showNormal();
	}
	/* 最大化 */
	else
	{
		/* 隐藏阴影边框 */
		ui->coreSystemGLayout->setMargin(0);

		/* 最大化 */
		showMaximized();
	}
}

/* 设置主题二级菜单的槽函数 */
void QLsCoreSystem::slotSetThemesActionsTriggered()
{
	/* 获取主题名 */
	QAction *action = qobject_cast<QAction *>(sender());
	QString themeName = action->text();
	if(m_curThemeName == themeName)
	{
		action->setChecked(true);
		return;
	}

	/* 加载主题 */
	if(!ui->showTabWidget->themesManager()->LoadTheme(this, themeName))
	{
		action->setChecked(true);
		return;
	}

	/* 更新样式 */
	/* 原来的样式取消选中 */
	foreach(auto iAction, ((QMenu *)ui->setBtn->menu()->children()[1])->actions())
	{
		if(iAction->text() == m_curThemeName)
		{
			iAction->setChecked(false);
			break;
		}
	}

	/* 更新为当前样式 */
	m_curThemeName = themeName;
	action->setChecked(true);
	QLOG_INFO() << "加载主题" << m_curThemeName.toUtf8().data();
}

/* 插件管理二级菜单的槽函数 */
void QLsCoreSystem::slotPluginManagerActionsTriggered()
{
	/* 获取插件名 */
	QAction *action = qobject_cast<QAction *>(sender());
	QString interfaceName = action->text();

	/* 获取插件信息 */
	QLsPluginsManager *pluginsManager = QLsPluginsManagerPool::GetInstance().GetPluginsManagerByPluginsDir("plugins");
	PluginInfo info = pluginsManager->GetPluginInfoByInterfaceName(interfaceName);

	emit sigLoad(info);
}

/* 日志输出到控件 */
void QLsCoreSystem::slotWriteLog(const QString &message, int level)
{
	/* 解析日志字符串"类型 时间 内容" */
	int levelLen = 5;													/* 前5个字节是类型 */
	int timeLen = 23;													/* 中间23个字节是时间 */
	int textLen = message.size() - (levelLen + 1) - (timeLen + 1);		/* 9之后的剩下的是内容 */

	QString levelStr = message.left(levelLen);
	QString timeStr = message.mid(levelLen + 1, timeLen);
	QString textStr = message.right(textLen);

	QTableWidgetItem *levelItem = new QTableWidgetItem(levelStr);
	QTableWidgetItem *timeItem = new QTableWidgetItem(timeStr);
	QTableWidgetItem *textItem = new QTableWidgetItem(textStr);

	/* 显示到日志表格上 */
	int row = ui->recordTableWidget->rowCount();
	ui->recordTableWidget->insertRow(row);
	ui->recordTableWidget->setItem(row, 0, levelItem);
	ui->recordTableWidget->setItem(row, 1, timeItem);
	ui->recordTableWidget->setItem(row, 2, textItem);

	/* 鼠标悬停提示完整内容 */
	textItem->setToolTip(textStr);

	/* 当前行自动下移 */
	ui->recordTableWidget->setCurrentCell(row, 0);

	/* 去除警告 */
	Q_UNUSED(level)
}

/* 切换语言二级菜单的槽函数 */
void QLsCoreSystem::slotChangeLanguageActionsTriggered()
{
	/* 获取主题名 */
	QAction *action = qobject_cast<QAction *>(sender());
	QString langPack = action->text();
	if(m_curLangPack == langPack)
	{
		action->setChecked(true);
		return;
	}

	/* 加载主题 */
	if(!QLsLanguagesManager::GetInstance().LoadLangPack(langPack))
	{
		action->setChecked(false);
		return;
	}

	/* 更新样式 */
	/* 原来的样式取消选中 */
	foreach(auto iAction, ((QMenu *)ui->setBtn->menu()->children()[2])->actions())
	{
		if(iAction->text() == m_curLangPack)
		{
			iAction->setChecked(false);
			break;
		}
	}

	/* 更新为当前样式 */
	m_curLangPack = langPack;
	action->setChecked(true);
	QLOG_INFO() << "加载语言包" << m_curLangPack.toUtf8().data() << "成功，重启后才能生效！";
}

/* 登录的槽函数 */
void QLsCoreSystem::slotLogin(const User &user)
{
	me = user;

	show();

	/* 移动到鼠标所在显示器，并设置居中显示 */
	QLsFunc::MoveWidgetToScreenWhereMouse(this);

	/* 获取显示器列表 */
	QList<QScreen *> screenList = QGuiApplication::screens();
	foreach (QScreen *screen, screenList)
	{	/* 找到鼠标所在显示器 */
		if(screen->geometry().contains(QCursor::pos()))
		{
#if AUTO_ScaleUI
			/* 缩放比例 */
			connect(screen, &QScreen::logicalDotsPerInchChanged,
					this, &QLsCoreSystem::onLogicalDotsPerInchChanged);
#endif
			break;
		}
	}

	/* 初始最大化界面（结合上一步，会在鼠标所在显示器最大化显示） */
//	on_maxiBtn_clicked();
}

/* 插件管理器最小尺寸变化的槽函数 */
void QLsCoreSystem::slotShowTabWidgetChangeMinimumSize(QSize size)
{
	/* 最小宽度变化 */
	if(size.width())
	{
		m_miniWidth += size.width();
		m_tabWidgetMiniWidth += size.width();
		setMinimumWidth(m_miniWidth);
	}

	/* 最小高度变化 */
	if(size.height())
	{
		m_miniHeight += size.height();
		m_tabWidgetMiniHeight += size.height();
		setMinimumHeight(m_miniHeight);
	}

	/* BUG:2020-10-09 15:36：√如果当前为最大化状态，修改窗口尺寸会假死 */
	if(!isMaximized()) resize(qMax(MIN_WIDTH, m_miniWidth), qMax(MIN_HEIGHT, m_miniHeight));
}
#if AUTO_ScaleUI
/* windows缩放(每英寸逻辑点)的变化 的槽函数 */
void QLsCoreSystem::onLogicalDotsPerInchChanged(qreal dpi)
{
	m_scaleFromPreRate = (double)dpi / 96 / m_preRate;
	m_preRate = (double)dpi / 96;
	SetSizeWithScale(*this);
}
#endif
/* 日志表格右键菜单 */
void QLsCoreSystem::on_recordTableWidget_customContextMenuRequested(const QPoint &pos)
{
	QTableWidgetItem *selecteditem = ui->recordTableWidget->itemAt(pos);
	if(!selecteditem) return;

	/* 清空 */
	QAction *clearAction = new QAction(tr("清空"), this);
	clearAction->setObjectName("clearAction");
	connect(clearAction, &QAction::triggered, this, &QLsCoreSystem::slotRecordActionDeal);

	/* 删除 */
	QAction *deleteAction = new QAction(tr("删除"), this);
	deleteAction->setObjectName("deleteAction");
	deleteAction->setData(selecteditem->row());
	connect(deleteAction, &QAction::triggered, this, &QLsCoreSystem::slotRecordActionDeal);

	/* 弹出菜单 */
	QMenu *menu = new QMenu(this);
	menu->setObjectName("recordTableWidgetMenu");
	menu->addAction(clearAction);
	menu->addAction(deleteAction);
	menu->popup(ui->recordTableWidget->viewport()->mapToGlobal(pos));
}

/* 日志表格右键菜单消息处理的槽函数 */
void QLsCoreSystem::slotRecordActionDeal()
{
	QAction *action = qobject_cast<QAction*>(sender());
	if (!action) return;

	QMutexLocker locker(&m_recordTableWidgetMutex);

	/* 清空 */
	if(action->text() == tr("清空"))
	{	/* 只删内容，不清空设置 */
		while(ui->recordTableWidget->rowCount())
			ui->recordTableWidget->removeRow(0);
	}
	/* 删除 */
	else if(action->text() == tr("删除"))
	{
		ui->recordTableWidget->removeRow(action->data().toInt());
	}
}

/* 加载、卸载插件的槽函数 */
void QLsCoreSystem::slotPluginLoad(PluginInfo &pluginInfo)
{
	/* 根据name找到action */
	QAction *action = nullptr;
	foreach(QAction *iAction, ((QMenu *)ui->setBtn->menu()->children()[2])->actions())
	{
		if(iAction->text() == pluginInfo.m_interfaceInfo->m_name)
		{
			action = iAction;
			break;
		}
	}

	if(!action) return;

	/* 卸载插件 */
	if(pluginInfo.m_isLoaded)
	{
		/* 菜单栏改为卸载状态 */
		action->setChecked(false);
	}
	/* 加载插件 */
	else
	{
		/* 菜单栏改为加载状态 */
		action->setChecked(true);
	}
}
